// #include "dev_ctrl.h"
#include <linux/delay.h>
#include <linux/fs.h>
#include <linux/gpio.h>
#include <linux/init.h>
#include <linux/input-event-codes.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_gpio.h>
#include <linux/platform_device.h>
#include <linux/pwm.h>
#include <linux/uaccess.h>
#define CNAME "fan_driver"
#define HZ_TO_NANOSECONDS(x) (1000000000UL / (x))

int major, value = 200;
#define  FAN_ON  1
#define  FAN_OFF 0
struct class *cls;
struct pwm_fan {
  struct pwm_device *pwm;
  unsigned long period;
};
struct pwm_fan *fan;
int fan_open(struct inode *inode, struct file *file) {
  printk("%s:%s:%d\n", __FILE__, __func__, __LINE__);
  return 0;
}
long fan_ioctl(struct file *file, unsigned int cmd, unsigned long arg) {
  int ret;
  switch (cmd) {
  case FAN_ON:
    //在收到FAN_OFF命令之前持续转动风扇
    fan->period = HZ_TO_NANOSECONDS(value);
    ret = pwm_config(fan->pwm, fan->period / 2, fan->period);
    if (ret) {
      printk("pwm config error\n");
      return ret;
    }
    ret = pwm_enable(fan->pwm);
    if (ret) {
      printk("pwm enable error\n");
      return ret;
    }
    break;
  case FAN_OFF:
    pwm_disable(fan->pwm);
    break;
  default:
    return -EINVAL;
  }
  return 0;
}
int fan_close(struct inode *inode, struct file *file) {
  printk("%s:%s:%d\n", __FILE__, __func__, __LINE__);
  return 0;
}
const struct file_operations fops = {
    .open = fan_open,
    .release = fan_close,
    .unlocked_ioctl = fan_ioctl,
};
int fan_probe(struct platform_device *pdev) {
  struct device *dev = &pdev->dev;
  fan = kzalloc(sizeof(*fan), GFP_KERNEL);
  if (!fan) {
    printk("fan kzalloc error\n");
    return -ENOMEM;
  }
  fan->pwm = pwm_get(dev, NULL);
  if (IS_ERR(fan->pwm)) {
    printk("failed to request pwm device:%ld\n", PTR_ERR(fan->pwm));
  }
  printk("+++++++test1========\n");
  major = register_chrdev(0, CNAME, &fops);
  if (major < 0) {
    printk("register chrdev error\n");
    return major;
  }
  printk("+++++++test1========\n");
  cls = class_create(THIS_MODULE, CNAME);
  if (IS_ERR(cls)) {
    printk("class create error\n");
    return PTR_ERR(cls);
  }
  printk("+++++++test2========\n");
  dev = device_create(cls, NULL, MKDEV(major, 0), NULL, CNAME);
  if (IS_ERR(dev)) {
    printk("device create error\n");
    return PTR_ERR(dev);
  }
  printk("+++++++test3========\n");
  return 0;
}
int fan_remove(struct platform_device *pdev) {
  device_destroy(cls, MKDEV(major, 0));
  class_destroy(cls);
  unregister_chrdev(major, CNAME);
  if (NULL != fan) {
    pwm_disable(fan->pwm);
    pwm_free(fan->pwm);
  }
  kfree(fan);
  return 0;
}
const struct of_device_id ofmatch[] = {{
                                           .compatible = "pwm-fan",
                                       },
                                       {}};
struct platform_driver fan_pwm = {.probe = fan_probe,
                                  .remove = fan_remove,
                                  .driver = {
                                      .name = "fan",
                                      .of_match_table = ofmatch,
                                  }};

MODULE_DEVICE_TABLE(of, ofmatch);
module_platform_driver(fan_pwm);
MODULE_LICENSE("GPL");